Skip to content

Fixed and lossy equal-balanced placement, reverse SPF (0.9.0) - #9

Merged
networmix merged 1 commit into
mainfrom
feature/ecmp-fixed-lossy
Sep 12, 2026
Merged

networmix merged 1 commit into
mainfrom
feature/ecmp-fixed-lossy

Conversation

@networmix

Copy link
Copy Markdown
Owner

Summary

  • EQUAL_BALANCED_FIXED: lossless hash-ECMP admission over the topology's next-hop set; a member filled by an earlier placement blocks later ones (scale 0).
  • EQUAL_BALANCED_LOSSY: best-effort fill-and-drop; placed is the delivered volume, FlowGraph.place_with_drops reports dropped volume per edge. FlowPolicy skips the equalizing rebalance for this mode so pinned routes carry what fits.
  • shortest_paths_to / Algorithms.spf_to: reverse SPF returning distances to a destination and a forward-oriented DAG usable from any node, with optional forced fan-out edges.
  • Cost-only FlowPolicies no longer pass residuals to SPF when an equal-balanced per-flow target is set (residuals force capacity-aware selection).
  • Version bumped to 0.9.0; changelog updated.

NetGraph 0.23.0 depends on this release (netgraph-core>=0.9.0).

Test plan

  • 170 C++ tests (make cpp-test)
  • Python suite and lint (make lint, pytest tests/py)
  • NetGraph full check and dev/check_core_integration.sh against this branch (1274 tests)

🤖 Generated with Claude Code

Two equal-balanced placement modes for hop-by-hop ECMP with a load-blind
forwarding table: EQUAL_BALANCED_FIXED admits losslessly over the
topology's next-hop set (a member filled since the DAG was computed drives
the scale to 0), EQUAL_BALANCED_LOSSY forwards best-effort and reports the
dropped volume per edge via FlowGraph.place_with_drops. FlowPolicy treats
both as equal-balanced but skips the equalizing rebalance for the lossy
mode, so pinned routes carry what fits.

shortest_paths_to / Algorithms.spf_to runs Dijkstra over the in-adjacency
and returns distances to one destination plus a forward-oriented PredDAG
valid for placement from any node, with optional forced fan-out edges for
an origin whose first hop is a traffic split rather than a routing choice.

A cost-only FlowPolicy (require_capacity=false) no longer passes the
residual to SPF when an equal-balanced per-flow target is set; a residual
forces capacity-aware selection, so such policies routed around saturated
edges instead of following costs.

Version 0.9.0.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
@chatgpt-codex-connector

chatgpt-codex-connector Bot commented Sep 12, 2026

Copy link
Copy Markdown

Codex Review Summary

This comment shows the latest Codex review activity on this pull request.

Review Status Commit Review trigger
📝 Code Review Completed 2026-09-12T23:07:10.055675Z 480e797 PR opened
ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review" or "@codex security review".

Codex reacts with 👀 while any review is running, comments if it has suggestions, and reacts with 👍 once all reviews finish with no findings.

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 480e7977fc

ℹ️ About Codex in GitHub

Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".

Comment thread src/shortest_paths.cpp
if (ent_edge[static_cast<std::size_t>(i)] == e_raw) { present = true; break; }
}
if (present) continue;
succ_append(static_cast<std::size_t>(u), v, e_raw);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Validate cycles after appending forced fan-out edges

The acyclicity check only considers entries produced by SPF, so a forced edge can itself introduce a cycle. For example, on a graph containing 0->1 and a higher-cost self-loop 0->0, passing the self-loop in fanout_edges reaches this append because node 0 has no incoming SPF entry, producing a cyclic PredDAG; a reproduced 10-unit EqualBalancedFixed placement then reported 8 units placed while allocating 10 units on both edges. Multiple forced edges between otherwise root nodes can similarly form cycles, so reject self-loops and validate the accumulated forced-edge graph before returning it.

AGENTS.md reference: AGENTS.md:L12-L12

Useful? React with 👍 / 👎.

@networmix
networmix merged commit 07de60d into main Sep 12, 2026
24 checks passed
@networmix
networmix deleted the feature/ecmp-fixed-lossy branch September 12, 2026 23:12
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant